﻿using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
using UnityEditor;
using UnityEngine;
using Debug = UnityEngine.Debug;

namespace XUProtobuf
{
    namespace Editor
    {
        internal class XUProtobufConverter
        {
            [MenuItem("Assets/XUProtobuf/Convert", false, 3)]
            public static void Convert()
            {
                XUProtobufConverterSetting setting = XUProtobufConverterSetting.LoadOrCreate();
                if (string.IsNullOrEmpty(setting.protoFolder) || !Directory.Exists(setting.protoFolder))
                {
                    EditorUtility.DisplayDialog("错误", "proto 路径错误", "确定");
                }
                else if (string.IsNullOrEmpty(setting.csFolder) || !Directory.Exists(setting.csFolder))
                {
                    EditorUtility.DisplayDialog("错误", "cs 路径错误", "确定");
                }
                else
                {
                    Generate(setting.protoFolder, setting.csFolder);
                    AssetDatabase.Refresh();
                }
            }

            static public void Generate(string protoDir, string csDir)
            {
                protoDir = Path.GetFullPath(protoDir);
                csDir = Path.GetFullPath(csDir);

                string exeFromPath = "protoc.exe";
                {
                    List<string> allFiles = new List<string>();
                    string folder1 = Application.dataPath.Replace("Assets", "Packages");
                    string folder2 = Application.dataPath.Replace("Assets", "Library/PackageCache");
                    allFiles.AddRange(Directory.GetFiles(folder1, exeFromPath, SearchOption.AllDirectories));
                    allFiles.AddRange(Directory.GetFiles(folder2, exeFromPath, SearchOption.AllDirectories));
                    foreach (string file in allFiles)
                    {
                        if (file.ToLower().Contains("protobuf"))
                        {
                            exeFromPath = file;
                            break;
                        }
                    }
                    if (!File.Exists(exeFromPath))
                    {
                        Debug.LogError("找不到 protoc.exe ");
                        return;
                    }
                }

                List<string> allProto = new List<string>();
                {
                    allProto.AddRange(Directory.GetFiles(protoDir, "*.proto", SearchOption.AllDirectories));
                    if (allProto.Count == 0)
                    {
                        Debug.LogError("找不到 proto 文件");
                        return;
                    }
                }

                List<string> batContent = new List<string>();
                {
                    foreach (var proto in allProto)
                    {
                        batContent.Add(string.Format("\"{0}\" -I=\"{1}\" --csharp_out=\"{2}\" \"{3}\"", exeFromPath, protoDir, csDir, proto));
                    }
                }
                string batSavePath = Application.dataPath.Replace("Assets", "Library/XUProtobuf/protoc.bat");
                string batSvaeFolder = Path.GetDirectoryName(batSavePath);
                if (!Directory.Exists(batSvaeFolder))
                {
                    Directory.CreateDirectory(batSvaeFolder);
                }
                File.WriteAllLines(batSavePath, batContent.ToArray());

                RunCommand(batSavePath);

                Debug.Log("proto转cs完成.");
            }

            public static void RunCommand(string batPath)
            {
                ProcessStartInfo info = new ProcessStartInfo();
                info.WorkingDirectory = Path.GetDirectoryName(batPath);
                info.FileName = batPath;
                info.CreateNoWindow = false;
                info.ErrorDialog = true;
                info.UseShellExecute = true;

                if (info.UseShellExecute)
                {
                    info.RedirectStandardOutput = false;
                    info.RedirectStandardError = false;
                    info.RedirectStandardInput = false;
                }
                else
                {
                    info.RedirectStandardOutput = true;
                    info.RedirectStandardError = true;
                    info.RedirectStandardInput = true;
                    info.StandardOutputEncoding = Encoding.UTF8;
                    info.StandardErrorEncoding = Encoding.UTF8;
                }

                Process process = Process.Start(info);

                if (!info.UseShellExecute)
                {
                    Debug.Log(process.StandardOutput);
                    Debug.Log(process.StandardError);
                }

                process.WaitForExit();
                process.Close();
            }
        }
    }
}
